/**
 * outsider.com.cn Inc.
 * Copyright (c) 2011-2022 All Rights Reserved.
 */
package com.yuanmeng.auth.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import com.alibaba.fastjson.JSON;
import com.yuanmeng.auth.form.ApiLoginBody;
import com.yuanmeng.common.core.constant.Constants;
import com.yuanmeng.common.core.constant.SecurityConstants;
import com.yuanmeng.common.core.domain.R;
import com.yuanmeng.common.core.enums.ErrorCodeEnum;
import com.yuanmeng.common.core.enums.LoginTypeEnum;
import com.yuanmeng.common.core.enums.StatusEnum;
import com.yuanmeng.common.core.enums.WxLoginTypeEnum;
import com.yuanmeng.common.core.exception.ServiceException;
import com.yuanmeng.common.core.handler.FormatValidateHandler;
import com.yuanmeng.common.core.handler.ObjectValidateHandler;
import com.yuanmeng.common.core.handler.RemoteValidateHandler;
import com.yuanmeng.common.core.utils.StringUtils;
import com.yuanmeng.common.security.utils.SecurityUtils;
import com.yuanmeng.system.api.RemoteApiUserService;
import com.yuanmeng.system.api.RemoteLogService;
import com.yuanmeng.system.api.RemoteSmsService;
import com.yuanmeng.system.api.domain.UserInfoEntity;
import com.yuanmeng.system.api.domain.request.ApiAddUserInfoRequest;
import com.yuanmeng.system.api.domain.request.ApiQueryUserInfoRequest;
import com.yuanmeng.system.api.domain.request.ModifyUserLoginInfoRequest;
import com.yuanmeng.system.api.domain.request.ValidateVerifyRequest;
import com.yuanmeng.system.api.domain.response.UserInfoResponse;

/**
 * @author outsider
 * @version Id: ApiUserLoginService.java, v 0.1 2022/6/6 17:08 outsider Exp $$
 */
@Component
public class ApiUserLoginService {
    protected final Logger       logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private RemoteApiUserService remoteApiUserService;

    @Autowired
    private RemoteLogService     remoteLogService;

    @Autowired
    private SysLoginService      sysLoginService;

    @Autowired
    private RemoteSmsService     remoteSmsService;

    /**
     * 登录
     */
    public UserInfoEntity userLogin(ApiLoginBody loginBody) {
        if (null == loginBody || StringUtils.isBlank(loginBody.getLoginType())) {
            sysLoginService.recordLogininfor("", Constants.LOGIN_FAIL, "账户信息不能为空");
            throw new ServiceException("账户信息不能为空");
        }
        UserInfoEntity userInfoEntity = null;

        // 密码登录
        if (LoginTypeEnum.PASSWORD.getCode().equals(loginBody.getLoginType())) {
            userInfoEntity = this.passwordLogin(loginBody);
        }

        // 验证码登录
        if (LoginTypeEnum.SMS.getCode().equals(loginBody.getLoginType())) {
            userInfoEntity = this.smsLogin(loginBody);
        }

        // 微信登录
        if (LoginTypeEnum.UNION_ID.getCode().equals(loginBody.getLoginType())) {
            WxLoginTypeEnum.validateWxLoginType(loginBody.getWxLoginType());
            if (WxLoginTypeEnum.APPLET.getCode().equals(loginBody.getWxLoginType())) {
                ObjectValidateHandler.requestParamWithNull(loginBody.getOpenId(),
                    "微信小程序openId不能为空");
            }
            userInfoEntity = this.weChatLogin(loginBody);
        }

        // IOS登录
        if (LoginTypeEnum.IOS_NO.getCode().equals(loginBody.getLoginType())) {
            userInfoEntity = this.iosLogin(loginBody);
        }
        return userInfoEntity;
    }

    /**
     * 验证用户信息是否存在
     * @param loginBody
     */
    private UserInfoEntity userInfoValidate(ApiLoginBody loginBody,
                                            ApiQueryUserInfoRequest request) {
        logger.info("用户登录请求参数为：{}", JSON.toJSON(loginBody));
        logger.info("微信号查询用户信息请求参数为：{}", JSON.toJSON(request));
        R<UserInfoResponse> userInfoResult = remoteApiUserService.queryMemberInfo(request,
            SecurityConstants.INNER);

        RemoteValidateHandler.remoteServiceFailHandler(userInfoResult);

        UserInfoResponse userInfoResponse = userInfoResult.getData();

        logger.info("微信号查询用户信息返回结果为：{}", JSON.toJSON(userInfoResponse));

        if (null != userInfoResponse.getUserInfoEntity()) {
            if (WxLoginTypeEnum.APPLET.getCode().equals(loginBody.getWxLoginType())) {
                if (!loginBody.getPhoneNo()
                    .equals(userInfoResponse.getUserInfoEntity().getPhoneNo())) {
                    throw new ServiceException(ErrorCodeEnum.WX_APPLET_FIRST_LOGIN_PHONE_NO_ERROR);
                }
            }
            return userInfoResponse.getUserInfoEntity();
        }
        // 用户手机号注册
        if (LoginTypeEnum.SMS.getCode().equals(loginBody.getLoginType())) {
            ApiAddUserInfoRequest addUserInfoRequest = new ApiAddUserInfoRequest();
            addUserInfoRequest.setPhoneNo(loginBody.getUsername());
            userInfoResponse = this.userRegister(loginBody, request, addUserInfoRequest);
            return userInfoResponse.getUserInfoEntity();
        }

        // 校验手机号不能为空
        ObjectValidateHandler.requestParamWithNull(loginBody.getPhoneNo(), "用户手机号不能为空");

        ApiQueryUserInfoRequest userInfoRequest = new ApiQueryUserInfoRequest();
        userInfoRequest.setPhoneNo(loginBody.getPhoneNo());
        userInfoRequest.setQueryType("LOGIN");

        logger.info("手机号查询用户信息请求参数为：{}", JSON.toJSON(request));

        R<UserInfoResponse> userInfoByPhoneNo = remoteApiUserService
            .queryMemberInfo(userInfoRequest, SecurityConstants.INNER);

        RemoteValidateHandler.remoteServiceFailHandler(userInfoByPhoneNo);

        UserInfoEntity userInfoEntity = userInfoByPhoneNo.getData().getUserInfoEntity();

        logger.info("手机号查询用户信息返回结果为：{}", JSON.toJSON(userInfoEntity));

        // 手机号及微信或IOS账号均不存在用户
        if (null == userInfoEntity) {
            ApiAddUserInfoRequest addUserInfoRequest = new ApiAddUserInfoRequest();
            addUserInfoRequest.setPhoneNo(loginBody.getPhoneNo());
            if (LoginTypeEnum.UNION_ID.getCode().equals(loginBody.getLoginType())) {
                addUserInfoRequest.setUnionId(loginBody.getUsername());
                addUserInfoRequest.setOpenId(loginBody.getOpenId());
                addUserInfoRequest.setPhotoUrl(loginBody.getPhotoUrl());
            }
            if (LoginTypeEnum.IOS_NO.getCode().equals(loginBody.getLoginType())) {
                addUserInfoRequest.setIosNo(loginBody.getUsername());
            }
            userInfoResponse = this.userRegister(loginBody, request, addUserInfoRequest);
            return userInfoResponse.getUserInfoEntity();
        }

        // 更新微信及IOS账号信息至用户信息
        ModifyUserLoginInfoRequest modifyUserOpenIdRequest = new ModifyUserLoginInfoRequest();
        modifyUserOpenIdRequest.setUserInfoId(userInfoEntity.getId());
        if (LoginTypeEnum.UNION_ID.getCode().equals(loginBody.getLoginType())) {
            modifyUserOpenIdRequest.setUnionId(loginBody.getUsername());
            modifyUserOpenIdRequest.setOpenId(loginBody.getOpenId());
            modifyUserOpenIdRequest.setPhotoUrl(loginBody.getPhotoUrl());
        }
        if (LoginTypeEnum.IOS_NO.getCode().equals(loginBody.getLoginType())) {
            modifyUserOpenIdRequest.setIosNo(loginBody.getUsername());
        }

        R result = remoteApiUserService.modifyMemberLoginInfo(modifyUserOpenIdRequest,
            SecurityConstants.INNER);
        RemoteValidateHandler.remoteServiceFailHandler(result);

        R<UserInfoResponse> userResult = remoteApiUserService.queryMemberInfo(request,
            SecurityConstants.INNER);
        RemoteValidateHandler.remoteServiceFailHandler(userResult);
        return userResult.getData().getUserInfoEntity();
    }

    /**
     * 用户注册
     * @param loginBody
     * @param request
     * @return
     */
    private UserInfoResponse userRegister(ApiLoginBody loginBody, ApiQueryUserInfoRequest request,
                                          ApiAddUserInfoRequest addUserInfoRequest) {

        addUserInfoRequest.setNickName(loginBody.getNickName());
        addUserInfoRequest.setPhotoUrl(loginBody.getPhotoUrl());
        addUserInfoRequest.setInvitationId(loginBody.getInvitationId());

        R<Boolean> insertRes = remoteApiUserService.userRegister(addUserInfoRequest,
            SecurityConstants.INNER);
        RemoteValidateHandler.remoteServiceFailHandler(insertRes);

        R<UserInfoResponse> result = remoteApiUserService.queryMemberInfo(request,
            SecurityConstants.INNER);
        RemoteValidateHandler.remoteServiceFailHandler(result);

        return result.getData();
    }

    /**
     * 用户状态校验
     * @param status
     */
    private void userStatusValidate(String status, String userName) {
        if (StatusEnum.DISABLE.getCode().equals(status)) {
            sysLoginService.recordLogininfor(userName, Constants.LOGIN_FAIL, "登录api用户被禁用，请联系客服处理!");
            throw new ServiceException("登录api用户：" + userName + " 被禁用，请联系客服处理!");
        }
    }

    /**
     * 手机验证码登录
     * @param loginBody
     * @return
     */
    private UserInfoEntity smsLogin(ApiLoginBody loginBody) {
        FormatValidateHandler.phoneNumValidate(loginBody.getUsername());

        if (StringUtils.isBlank(loginBody.getSmsCode())) {
            throw new ServiceException(ErrorCodeEnum.VERIFY_CODE_IS_NOT_NULL_ERROR);
        }
        // 短信验证码校验
        ValidateVerifyRequest verifyRequest = new ValidateVerifyRequest();
        verifyRequest.setPhoneNo(loginBody.getUsername());
        verifyRequest.setVerifyCode(loginBody.getSmsCode());

        R validateVerifyCode = remoteSmsService.validateVerifyCode(verifyRequest,
            SecurityConstants.INNER);
        RemoteValidateHandler.remoteServiceFailHandler(validateVerifyCode);
        // 查询用户是否存在
        ApiQueryUserInfoRequest request = new ApiQueryUserInfoRequest();
        request.setPhoneNo(loginBody.getUsername());
        request.setQueryType("LOGIN");

        // 验证用户信息是否存在
        UserInfoEntity userInfoEntity = userInfoValidate(loginBody, request);

        // 用户状态校验
        userStatusValidate(userInfoEntity.getStatus(), loginBody.getUsername());

        return userInfoEntity;
    }

    /**
     * 微信登录
     * @param loginBody
     * @return
     */
    private UserInfoEntity weChatLogin(ApiLoginBody loginBody) {
        ApiQueryUserInfoRequest queryUserInfoRequest = new ApiQueryUserInfoRequest();
        queryUserInfoRequest.setUnionId(loginBody.getUsername());
        queryUserInfoRequest.setQueryType("LOGIN");

        // 验证用户信息是否存在
        UserInfoEntity userInfoEntity = userInfoValidate(loginBody, queryUserInfoRequest);

        // 用户状态校验
        userStatusValidate(userInfoEntity.getStatus(), loginBody.getUsername());

        // 校验小程序用户第一次登录，更新openId
        if (WxLoginTypeEnum.APPLET.getCode().equals(loginBody.getWxLoginType())) {
            ObjectValidateHandler.requestParamWithNull(loginBody.getPhoneNo(), "小程序登录手机号不能为空");
            if (StringUtils.isBlank(userInfoEntity.getOpenId())
                || !ObjectUtils.isEmpty(loginBody.getPhotoUrl())) {
                // 更新小程序openId
                ModifyUserLoginInfoRequest request = new ModifyUserLoginInfoRequest();
                request.setUserInfoId(userInfoEntity.getId());
                request.setOpenId(loginBody.getOpenId());
                request.setPhotoUrl(loginBody.getPhotoUrl());

                R result = remoteApiUserService.modifyMemberLoginInfo(request,
                    SecurityConstants.INNER);
                RemoteValidateHandler.remoteServiceFailHandler(result);
                userInfoEntity.setOpenId(loginBody.getOpenId());
            }
        }
        return userInfoEntity;
    }

    /**
     * ios登录
     * @param loginBody
     * @return
     */
    private UserInfoEntity iosLogin(ApiLoginBody loginBody) {
        ApiQueryUserInfoRequest queryUserInfoRequest = new ApiQueryUserInfoRequest();
        queryUserInfoRequest.setIosNo(loginBody.getUsername());
        queryUserInfoRequest.setQueryType("LOGIN");

        // 验证用户信息是否存在
        UserInfoEntity userInfoEntity = userInfoValidate(loginBody, queryUserInfoRequest);

        // 用户状态校验
        userStatusValidate(userInfoEntity.getStatus(), loginBody.getUsername());

        return userInfoEntity;
    }

    /**
     * 密码登录
     * @param loginBody
     * @return
     */
    private UserInfoEntity passwordLogin(ApiLoginBody loginBody) {
        ObjectValidateHandler.requestParamWithNull(loginBody.getPassword(), "密码不能为空");

        ApiQueryUserInfoRequest queryUserInfoRequest = new ApiQueryUserInfoRequest();
        queryUserInfoRequest.setPhoneNo(loginBody.getUsername());
        queryUserInfoRequest.setQueryType("PASSWORD");

        R<UserInfoResponse> userInfoResult = remoteApiUserService
            .queryMemberInfo(queryUserInfoRequest, SecurityConstants.INNER);

        RemoteValidateHandler.remoteServiceFailHandler(userInfoResult);

        UserInfoResponse userInfoResponse = userInfoResult.getData();

        logger.info("微信号查询用户信息返回结果为：{}", JSON.toJSON(userInfoResponse));

        ObjectValidateHandler.objectNotExistErrorHandler(userInfoResponse.getUserAccountEntity(),
            "用户账户信息不存在");

        if (!SecurityUtils.matchesPassword(loginBody.getPassword(),
            userInfoResponse.getUserAccountEntity().getLoginPassword())) {
            throw new ServiceException("用户名或密码错误");
        }

        // 用户状态校验
        userStatusValidate(userInfoResponse.getUserInfoEntity().getStatus(),
            loginBody.getUsername());

        return userInfoResponse.getUserInfoEntity();
    }

    /**
     * 用户注销业务处理
     * @param userId
     */
    public void userDeregisterBusiness(Long userId) {
        R result = remoteApiUserService.userDeregister(userId, SecurityConstants.INNER);
        RemoteValidateHandler.remoteServiceFailHandler(result);
    }
}